// index.ts
import axios from 'axios';
import router from '@/router';
import useAppStore from '@/stores';
import { Base } from './base';
import { showFailToast } from 'vant';
import 'vant/es/toast/style';

const baseURL = Base.env

/** 
 * 跳转登录页
 * 携带当前页面路由，以期在登录页面完成登录后返回当前页面
 */
const toLogin = () => {
  router.replace({
    name: 'LoginPage',
  });
}

/** 
 * 请求失败后的错误统一处理 
 * @param {Number} status 请求失败的状态码
 */
const errorHandle = (status: number, other: string) => {
  // 状态码判断
  switch (status) {
    case 302: showFailToast('接口重定向了！');
      break;
    case 400:
      showFailToast(`${status}，发出的请求有错误，服务器没有进行新建或修改数据的操作`)
      break;
    case 401: //重定向
      showFailToast('登录已失效,请重新登录!')
      localStorage.clear()
      toLogin()
      // router.replace({
      //   path: '/Login',
      // });
      break;
    case 404:
      showFailToast(`${status}，网络请求不存在`)
      break;
    case 500:
      showFailToast(`${status}，服务器发生错误，请检查服务器`)
      break;
    case 502:
      showFailToast(`${status}，网关错误`)
      break;
    case 503:
      showFailToast(`${status}，服务不可用，服务器暂时过载或维护`)
      break;
    case 504:
      showFailToast(`${status}，网关超时`)
      break;
    default:
      showFailToast(`${status}，请求错误`)
  }
}

/* 实例化请求配置 */
const instance = axios.create({
  // 请求头参数
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    'Access-Control-Allow-Origin-Type': '*'
  },

  // 请求时长
  timeout: 1000 * 30,

  // 请求的base地址 TODO:这块以后根据不同的模块调不同的api
  baseURL,

  // 表示跨域请求时是否需要使用凭证
  withCredentials: false,
})

/** 
 * 请求拦截器 
 */
instance.interceptors.request.use(
  (config: any) => {
    const appStore = useAppStore();

    if (appStore.token) {
      config.headers.Authorization = appStore.token;
    }
    return config;
  },
  (error: any) => {
    showFailToast(error.data);
    return Promise.reject(error.data);
  }
)

// 响应拦截器
instance.interceptors.response.use((response: any) => {
  // 请求成功
  if (response.status === 200 || response.status === 204) {
    return Promise.resolve(response);
  } else {
    return Promise.reject(response);
  }
}, (error: any) => {
  // 请求失败
  const { response } = error;
  if (response) {
    errorHandle(response.status, response.data.message);

    // 超时重新请求
    const config = error.config;
    // 全局的请求次数,请求的间隙
    const [RETRY_COUNT, RETRY_DELAY] = [3, 1000];

    if (config && RETRY_COUNT) {
      // 设置用于跟踪重试计数的变量
      config.__retryCount = config.__retryCount || 0;
      // 检查是否已经把重试的总数用完
      if (config.__retryCount >= RETRY_COUNT) {
        return Promise.reject(response || { message: error.message });
      }
      // 增加重试计数
      config.__retryCount++;
      // 创造新的Promise来处理指数后退
      const backoff = new Promise<void>((resolve) => {
        setTimeout(() => {
          resolve();
        }, RETRY_DELAY || 1);
      });
      // instance重试请求的Promise
      return backoff.then(() => {
        return instance(config);
      });
    }

    return Promise.reject(response);
  } else {
    // 处理断网的情况
    // eg:请求超时或断网时，更新state的network状态
    // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
    // 后续增加断网情况下做的一些操作
    useAppStore().setNetworkState(false);
  }
}
)
// 只需要考虑单一职责，这块只封装axios
export default instance
